<?php

namespace qore_base\base;
use \qore\base\Event;
use \Qore;

/**
 * @author Samuel Nogueira <samuel.nogueira.dev@gmail.com>
 */
abstract class Application extends Component {
	public $name;
	public $componentsConfig;
	
	public function init() {
		if (QORE_ENABLE_EXCEPTION_HANDLER) set_exception_handler(array($this, 'handleException'));
		if (QORE_ENABLE_ERROR_HANDLER) set_error_handler(array($this, 'handleError'));
	}
	
	/**
	 * Fetches configuration values for component
	 * @param string $class
	 * @return array
	 */
	public function getComponentsConfig($class) {
		return Qore::vget($this->componentsConfig, $class, array());
	}
	
	/**
	 * Handles uncaught PHP exceptions.
	 * This method is implemented as a PHP exception handler.
	 * The application will be terminated by this method.
	 * @param Exception $exception exception that is not caught
	 */
	public function handleException(\Exception $exception) {
		// disable error capturing to avoid recursive errors
		restore_error_handler();
		restore_exception_handler();
		
		$this->displayException($exception);
		$this->end(1);
	}

	/**
	 * Handles PHP execution errors such as warnings, notices.
	 * This method is implemented as a PHP error handler.
	 * The application will be terminated by this method.
	 *
	 * @param integer $code the level of the error raised
	 * @param string $message the error message
	 * @param string $file the filename that the error was raised in
	 * @param integer $line the line number the error was raised at
	 */
	public function handleError($code, $message, $file, $line) {
		throw new \ErrorException($message, 0, $code, $file, $line);
	}

	/**
	 * Displays the uncaught PHP exception.
	 * @param Exception $exception the uncaught exception
	 */
	public function displayException(\Exception $exception) {
		$class = get_class($exception);
		$message = $exception->getMessage();
		$file = $exception->getFile();
		$line = $exception->getLine();
		$trace = $exception->getTraceAsString();
		
		if (QORE_DEBUG) {
			echo "$class: $message ($file:$line)\n";
			echo $trace;
		} else {
			echo "$class: $message";
		}
	}

	abstract public function run();

	/**
	 * Terminates the application.
	 * This method replaces PHP's exit() function.
	 * @param integer $status exit status (value 0 means normal exit while other values mean abnormal exit).
	 * @param boolean $exit whether to exit the current request. This parameter has been available since version 1.1.5.
	 * It defaults to true, meaning the PHP's exit() function will be called at the end of this method.
	 */
	public function end($status=0, $exit=true) {
		$this->trigger('applicationEnd', new Event($this, array('status' => $status)));
		if ($exit) exit($status);
	}

}
